home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / packet / p_aa4re / mbb35src / 8530int.asm < prev    next >
Encoding:
Assembly Source File  |  1988-07-24  |  20.6 KB  |  483 lines

  1. ;==========================================================================;
  2. ; Interrupt service for 8530                                               ;
  3. ;                                                                          ;
  4. ;   Copyright 1986, 1987, 1988 by H. Roy Engehausen.  All rights reserved. ;
  5. ;   This software may be freely distributed and used, but it may not       ;
  6. ;   under any circumstances be sold by anyone other than the author.       ;
  7. ;   It may be distributed by a commercial company as long as it is         ;
  8. ;   for no cost.                                                           ;
  9. ;                                                                          ;
  10. ;   Permission is explicity granted to use this code as a model for        ;
  11. ;   other programs requiring interrupt driven serial I/O as long as they   ;
  12. ;   carry this copyright notice and the imbedded constants                 ;
  13. ;                                                                          ;
  14. ; Here we discover what woke us up                                         ;
  15. ;     Inputs:  DX = port address                                           ;
  16. ;              SI = suspected COM block                                    ;
  17. ;==========================================================================;
  18.  
  19.                                     ; AX, CX, DX, DI, SI already saved!
  20.                                     ; CS is ok.  DS is not!
  21.  
  22. scc_more:                           ; This label used when an interrupt
  23.                                     ; is serviced but there is more pending
  24.                                     ; Only SI and DX need be set.
  25.  
  26. ;--------------------------------------------------------------------------;
  27. ; What caused this 8530 interrupt.  Remember there are two com ports       ;
  28. ; involved.  We must always check on channel "B"                           ;
  29. ;--------------------------------------------------------------------------;
  30.  
  31.         AND     DX,scc_card_mask    ; Convert to address of card
  32.         MOV     DI,sccb_ctl         ; Port address of channel B control
  33.         ADD     DX,DI               ; Add card base to obtain real address
  34.  
  35.         MOV     AL,sccreg2          ; Select reg 2
  36.         OUT     DX,AL               ; Send it
  37.         IN      AL,DX               ; Read the thing
  38.  
  39.  
  40.         JMP     debug1              ; This is debugging code left in
  41.         ADD     AL,48               ; so we can test things by patching the
  42.         CALL    dispchar            ; JMP to a NOP
  43.         SUB     AL,48               ;
  44. debug1:
  45.  
  46. ;--------------------------------------------------------------------------;
  47. ; AL now contains the interrupt vector.  First thing is to get SI          ;
  48. ; pointing in the right direction.                                         ;
  49. ;--------------------------------------------------------------------------;
  50.  
  51.         TEST    AL,scc_int_mask     ; Is this interrupt on channel "A"
  52.         JZ      scc_int_b           ;      Nope...
  53.         TEST    BYTE PTR baseaddr[SI],scc_chan_mask ; Channel "A"?
  54.         JNZ     scc_int_do          ;      Yes... It all matches
  55.         MOV     SI,chip_comm[SI]    ; Get common chip data area
  56.         MOV     SI,DS:0[SI]         ; Get Channel "A" pointer
  57.         JMP     scc_int_do          ; Go handle interrupt
  58.  
  59. scc_int_b:
  60.  
  61.         TEST    BYTE PTR baseaddr[SI],scc_chan_mask ; Channel "B"?
  62.         JZ      scc_int_do          ;      Yes... It all matches
  63.         MOV     SI,chip_comm[SI]    ; Get common chip data area
  64.         MOV     SI,DS:2[SI]         ; Get Channel "B" pointer
  65.  
  66. scc_int_do:                         ;
  67.  
  68. ;--------------------------------------------------------------------------;
  69. ; SI points to the com block of the interrupting channel.  Go to the       ;
  70. ; routine we need!                                                         ;
  71. ;--------------------------------------------------------------------------;
  72.  
  73.         MOV     DX,baseaddr[SI]     ; Get port address
  74.  
  75.         AND     AL,0FFH-scc_int_mask ; Remove channel indicator!
  76.         CBW                         ; Clear top of register
  77.         MOV     DI,AX               ; Put in valid register
  78.         JMP     DS:scc_table[DI]    ; Go to it
  79.  
  80. ; Branches to proper handler.  DI = interrupt type, SI = com block,
  81. ;                              DX = Control port address for this channel
  82.  
  83. scc_table LABEL WORD
  84.         DW      OFFSET  scc_tbe     ; 0 = Transmit buffer empty
  85.         DW      OFFSET  scc_ext     ; 2 = External change
  86.         DW      OFFSET  scc_rda     ; 4 = Receive data available
  87.         DW      OFFSET  scc_src     ; 6 = Special receive condition
  88.  
  89. ;==========================================================================;
  90. ; Transmit buffer empty                                                    ;
  91. ;==========================================================================;
  92.  
  93. scc_tbe:
  94.  
  95.         PUSH    ES                  ; Use ES for stuff
  96.         MOV     ES,buffer_t_a[SI]   ; ES = transmit buffer segement
  97.  
  98.         MOV     DI,buffer_t_out[SI] ; Get current buffer position
  99.  
  100. scc_tbe_loop:
  101.  
  102.         INC     DI                  ; Bump to next
  103.         CMP     DI,ES:buffer_dl     ; End of packet?
  104.         JAE     scc_tbe_done        ;      Yes.. Must allow underrun to occur
  105.  
  106. ;--------------------------------------------------------------------------;
  107. ; Buffer not empty yet so send a character.                                ;
  108. ;--------------------------------------------------------------------------;
  109.  
  110.         MOV     buffer_t_out[SI],DI ; Save new current buffer position
  111.         MOV     AL,ES:[DI]          ; Get character to send
  112.  
  113.         OR      DL,scc_data_mask    ; Convert control port to data port address
  114.         OUT     DX,AL               ; Send the character
  115.  
  116.         AND     DL,0FFH-scc_data_mask ; Port address back
  117.  
  118.         IN      AL,DX               ; Get the status
  119.         TEST    AL,tx_tbe           ; Still hungry?
  120.         JNZ     scc_tbe_loop        ;      Yep.. Try again
  121.  
  122.         JMP     scc_tbe_exit        ; Exit
  123.  
  124. ;--------------------------------------------------------------------------;
  125. ; Buffer is empty.  End the packet                                         ;
  126. ;--------------------------------------------------------------------------;
  127.  
  128. scc_tbe_done:                       ;
  129.  
  130.         OR      flags[SI],flags_tbe ; Signal buffer done
  131.  
  132.         MOV     AX,ES:buffer_next   ; Next guy in the chain please
  133.         MOV     buffer_t_a[SI],AX   ;
  134.  
  135.         MOV     ES:buffer_next,0    ; Clear the link to prevent loops
  136.  
  137.         OR      ES:buffer_st1,buffer_st1_xmt ; Turn on transmitted bit
  138.  
  139.         TEST    ES:buffer_st1,buffer_st1_ddb ; Ok to free buffer?
  140.         JNZ     scc_tbe_no_free              ; Nope
  141.  
  142.         MOV     AX,ES               ; Free buffer thats in ES
  143.         CALL    free_a_buffer       ; Let the old buffer go!
  144.  
  145. scc_tbe_no_free:
  146.  
  147.         OR      flags[SI],flags_tbe ; Signal to expect eom
  148.  
  149.         MOV     period_xmtr[SI],period_x_crc ; Event = CRC delay
  150.         MOV     timer_xmtr[SI],0    ; Set transmitter timer to zero
  151.  
  152.         CALL    int_8530            ; Change interrupt service
  153.  
  154. ;--------------------------------------------------------------------------;
  155. ; Common TBE exit routine                                                  ;
  156. ;--------------------------------------------------------------------------;
  157.  
  158. scc_tbe_exit:
  159.  
  160.         POP     ES                  ; Done with ES
  161.  
  162.         MOV     AL,rst_txip         ; Reset transmitter interrupt pending
  163.         OUT     DX,AL               ; Put out
  164.  
  165.         JMP     scc_exit            ; Leave!
  166.  
  167. ;==========================================================================;
  168. ; External interrupt                                                       ;
  169. ;==========================================================================;
  170.  
  171. scc_ext:
  172.  
  173.         IN      AL,DX               ; Read Register 0 (needs no write)
  174.         MOV     last_rs[SI],AL      ; Save the status
  175.         MOV     AH,AL               ;      also in a register for later
  176.  
  177. ;--------------------------------------------------------------------------;
  178. ; Issue the external interrupt reset command                               ;
  179. ;--------------------------------------------------------------------------;
  180.  
  181.         MOV     AL,rst_ext          ; Issue Reset Ext Interrupt command
  182.         OUT     DX,AL               ; WR0 needs no prep
  183.  
  184. ;--------------------------------------------------------------------------;
  185. ; Is there a TX underrun/eom ?                                             ;
  186. ;--------------------------------------------------------------------------;
  187.  
  188.         CMP     period_xmtr[SI],period_x_tx ; Event = sending data
  189.         JNE     scc_ext_no_tx       ;      Nope.. Ignore this bit
  190.  
  191.         TEST    AH,tx_unrun         ; Under run?
  192.         JZ      scc_ext_no_tx       ;      Nope...
  193.  
  194. ; Handle underrun by turning off the transmitter and hoping nothing happens!
  195.  
  196.         AND     flags[SI],0FFH-flags_tbe ; Signal to expect eom?
  197.         MOV     period_xmtr[SI],period_x_crc ; Event = CRC delay
  198.         MOV     timer_xmtr[SI],0    ; Set transmitter timer to zero
  199.  
  200.         MOV     AL,sccreg5          ; WR5
  201.         OUT     DX,AL               ;
  202.         MOV     AL,dtr_pin+tx_8bits+rts_pin+tx_crcen+tx_enabl;
  203.         OUT     DX,AL               ;
  204.  
  205. scc_ext_no_tx:                      ;
  206.  
  207. ;--------------------------------------------------------------------------;
  208. ; If we have a break or abort, empty the receiver buffer.                  ;
  209. ;--------------------------------------------------------------------------;
  210.  
  211.         TEST    AH,rx_abort         ; Abort?
  212.         JZ      scc_ext_no_abort    ;      Nope
  213.  
  214. scc_ext_abort_rda:                  ;
  215.  
  216.         OR      DL,scc_data_mask    ; Get the data port address
  217.         IN      AL,DX               ; Grab the character
  218.         AND     DL,0FFH-scc_data_mask ; Convert back to control address
  219.  
  220.         IN      AL,DX               ; Get the latest status
  221.  
  222.         TEST    AL,rx_abort         ; Abort?
  223.         JZ      scc_ext_no_abort    ;      Nope
  224.         TEST    AL,rx_rda           ; RDA still?
  225.         JNZ     scc_ext_abort_rda   ;      Yep.. Try again
  226.  
  227.         MOV     buffer_r_in[SI],0   ; Zero the count in the buffer
  228.  
  229. scc_ext_no_abort:                   ;
  230.  
  231. ;--------------------------------------------------------------------------;
  232. ; Special routines for DCD on or off                                       ;
  233. ;--------------------------------------------------------------------------;
  234.  
  235.         TEST    AH,dcd_pin          ; DCD on?
  236.         JNZ     scc_ext_dcd_on      ;      Yep...
  237.  
  238. ;--------------------------------------------------------------------------;
  239. ; If DCD dropped then end the packet and reset the receiver                ;
  240. ;--------------------------------------------------------------------------;
  241.  
  242.         TEST    flags[SI],flags_dcd_on ; Was DCD on previously?
  243.         JZ      scc_ext_dcd_off     ;      Nope...
  244.  
  245.         AND     flags[SI],0FFH-flags_dcd_on ; Show DCD was off
  246.  
  247.         CALL    ron_8530            ; Initialize the receiver
  248.  
  249.         MOV     buffer_r_in[SI],0   ; Zero the count in the buffer
  250.  
  251. scc_ext_dcd_off:
  252.  
  253.         JMP     scc_exit            ; Leave!
  254.  
  255. ;--------------------------------------------------------------------------;
  256. ; If DCD just came on then ready the receiver                              ;
  257. ;--------------------------------------------------------------------------;
  258.  
  259. scc_ext_dcd_on:                     ;
  260.  
  261.         TEST    flags[SI],flags_dcd_on ; Was DCD on previously?
  262.         JNZ     scc_ext_dcd_ok      ;      Yep...
  263.  
  264.         OR      flags[SI],flags_dcd_on ; Show DCD was on
  265.  
  266.         CALL    ron_8530            ; Initialize the receiver
  267.  
  268.         MOV     buffer_r_in[SI],0   ; Zero the count in the buffer
  269.  
  270. scc_ext_dcd_ok:                     ;
  271.  
  272.         JMP     scc_exit            ; Leave!
  273.  
  274. ;==========================================================================;
  275. ; Receive Data Available                                                   ;
  276. ;==========================================================================;
  277.  
  278. scc_rda:
  279.  
  280.         OR      DL,scc_data_mask    ; Get the data port address
  281.         IN      AL,DX               ; Grab the character
  282.         AND     DL,0FFH-scc_data_mask ; Convert back to control address
  283.  
  284. ;--------------------------------------------------------------------------;
  285. ; Put the character away.  If no room, we will simulate an overrun!        ;
  286. ;--------------------------------------------------------------------------;
  287.  
  288.         MOV     DI,buffer_r_in[SI]  ; Where does it go?
  289.         CMP     DI,buffer_siz2      ;      but first, is there room?
  290.         JAE     scc_rda_overrun     ;      No room......
  291.  
  292.         PUSH    ES                  ; We will need ES
  293.         MOV     ES,buffer_r_a[SI]   ; Get buffer address
  294.         MOV     ES:[DI],AL          ; Stuff character in buffer
  295.         POP     ES                  ; Done with ES
  296.  
  297.         INC     DI                  ; Bump counter
  298.         MOV     buffer_r_in[SI],DI  ; And save it
  299.  
  300. scc_rda_overrun: ; Until we figure out something better
  301.  
  302. ;--------------------------------------------------------------------------;
  303. ; If there is more receive data, process it                                ;
  304. ;--------------------------------------------------------------------------;
  305.  
  306.         IN      AL,DX               ; RR0 (No select needed)
  307.  
  308.         TEST    AL,rx_rda           ; Any more data?
  309.         JNZ     scc_rda             ;      Yes.. try again
  310.  
  311.         MOV     last_rs[SI],AL      ; Save the status
  312.  
  313.         JMP     scc_exit            ; All done
  314.  
  315. ;==========================================================================;
  316. ; Special Receive Condition                                                ;
  317. ;==========================================================================;
  318.  
  319. scc_src:
  320.  
  321.         PUSH    ES                  ; Gonna need ES for
  322.         MOV     ES,buffer_r_a[SI]   ;      pointing to the receive buffer
  323.  
  324. ;--------------------------------------------------------------------------;
  325. ; Empty the receive buffer if anything left                                ;
  326. ;--------------------------------------------------------------------------;
  327.  
  328.         MOV     DI,buffer_r_in[SI]  ; Where does it go?
  329.  
  330. scc_src_data:
  331.  
  332.         IN      AL,DX               ; RR0 (no select needed)
  333.  
  334.         TEST    AL,rx_rda           ; Any more data?
  335.         JZ      scc_src_no_data     ;      Nope
  336.  
  337.         OR      DL,scc_data_mask    ; Get the data port address
  338.         IN      AL,DX               ; Grab the character
  339.         AND     DL,0FFH-scc_data_mask ; Convert back to control address
  340.  
  341.         CMP     DI,buffer_siz2      ; Room in buffer?
  342.         JAE     scc_src_overrun     ;      No room......
  343.  
  344.         MOV     ES:[DI],AL          ; Stuff character in buffer
  345.         INC     DI                  ; Bump counter
  346.  
  347. scc_src_overrun:
  348.         JMP     scc_src_data
  349.  
  350. scc_src_no_data:
  351.  
  352. ;--------------------------------------------------------------------------;
  353. ; Save the status bytes becuz this is packet end one way or another        ;
  354. ;--------------------------------------------------------------------------;
  355.  
  356.         MOV     ES:buffer_st1,AL    ; Save this as first status byte
  357.  
  358.         MOV     ES:buffer_dl,DI     ; Save the data length
  359.  
  360.         MOV     AL,sccreg1          ; We want R1
  361.         OUT     DX,AL               ;      so select it then
  362.         IN      AL,DX               ;      read it!
  363.  
  364.         MOV     ES:buffer_st2,AL    ; Save this as second status byte
  365.  
  366. ;--------------------------------------------------------------------------;
  367. ; Reset receive CRC if necessary                                           ;
  368. ;--------------------------------------------------------------------------;
  369.  
  370.         TEST    AL,rx_eof+rx_crcerr+rx_ovrn ;
  371.         JZ      scc_src_no_crc      ;
  372.  
  373.         MOV     AL,rst_rcrc         ; Reset RX CRC checker
  374.         OUT     DX,AL
  375.  
  376. scc_src_no_crc:                     ;
  377.  
  378. ;--------------------------------------------------------------------------;
  379. ; If packet in error and user don't want it then throw away.               ;
  380. ; Actually we will reuse the darn thing                                    ;
  381. ;--------------------------------------------------------------------------;
  382.  
  383.         TEST    options[SI],opt_igerr ; Ignore error?
  384.         JNZ     scc_src_noig        ;      Nope...
  385.         TEST    ES:buffer_st2,rx_crcerr+rx_ovrn ; Error?
  386.         JNZ     scc_src_ignore      ;      Nope.
  387.         TEST    ES:buffer_st1,rx_abort ;          Abort
  388.         JNZ     scc_src_ignore      ;      Nope.
  389.  
  390. scc_src_noig:
  391.  
  392. ;--------------------------------------------------------------------------;
  393. ; Save the packet and prepare for next one                                 ;
  394. ;--------------------------------------------------------------------------;
  395.  
  396.         MOV     DI,ES               ; Save current buffer address
  397.  
  398.         CALL    get_a_buffer        ; Get the new buffer for the chain
  399.         OR      AX,AX               ; Did we find one?
  400.         JZ      scc_src_no_buff     ;      Nope... Forget it
  401.         MOV     ES,AX               ; Address the new buffer
  402.  
  403.         MOV     ES:buffer_next,DI   ; Chain with most recent (the new one)
  404.         MOV     buffer_r_a[SI],ES   ; on the head
  405.  
  406. ;--------------------------------------------------------------------------;
  407. ; Read for next packet!                                                    ;
  408. ;--------------------------------------------------------------------------;
  409.  
  410. scc_src_ignore:                     ; Come here when ignoring a packet in error
  411.  
  412.         SUB     AX,AX               ; Zero the count of bytes in the
  413.         MOV     buffer_r_in[SI],AX  ;      receive buffer
  414.  
  415. scc_src_no_buff:                    ; No buffers available
  416.  
  417.         POP     ES                  ; All done with ES for now
  418.  
  419. ;--------------------------------------------------------------------------;
  420. ; Reset Register 1 status                                                  ;
  421. ;--------------------------------------------------------------------------;
  422.  
  423.         MOV     AL,rst_err1         ; Reset errors
  424.         OUT     DX,AL               ; Send it out
  425.  
  426. ;--------------------------------------------------------------------------;
  427. ; All done with this one                                                   ;
  428. ;--------------------------------------------------------------------------;
  429.  
  430. ;fallthru JMP     scc_exit            ; All done
  431.  
  432. ;==========================================================================;
  433. ; Interrupt exit!                                                          ;
  434. ;==========================================================================;
  435.  
  436. scc_exit:
  437.  
  438. ;--------------------------------------------------------------------------;
  439. ; Tell 8530 we are all done                                                ;
  440. ;--------------------------------------------------------------------------;
  441.  
  442.         MOV     DX,baseaddr[SI]     ; Get port address
  443.         MOV     AL,rst_ius          ; Reset highest interrupt under service
  444.         OUT     DX,AL
  445.  
  446. ;--------------------------------------------------------------------------;
  447. ; Tell the 8259 we are done                                                ;
  448. ;--------------------------------------------------------------------------;
  449.  
  450.         MOV     AL,pic_clear        ; Tell 8259 we are done
  451.  
  452.         TEST    options[SI],opt_high_irq ; Slave 8259 involved?
  453.         JZ      scc_pic_master      ; Nope
  454.  
  455.         OUT     pic2_cmd_port,AL    ; Clear slave
  456.  
  457. scc_pic_master:
  458.  
  459.         OUT     pic_cmd_port,AL     ; Clear master
  460.  
  461. ;--------------------------------------------------------------------------;
  462. ; See if anything left for this chip?                                      ;
  463. ;--------------------------------------------------------------------------;
  464.  
  465.         OR      DL,scc_chan_mask    ; Force us to channel "A"
  466.         MOV     AL,sccreg3          ; RR3 please
  467.         OUT     DX,AL               ;
  468.         IN      AL,DX               ;
  469.  
  470.         OR      AL,AL               ; Anything pending?
  471.         JZ      scc_ok_to_go        ;      Nope.. Leave
  472.  
  473.         MOV     DX,baseaddr[SI]     ; Get port address
  474.         JMP     scc_more            ; Go service the interrupts
  475.  
  476. scc_ok_to_go:                       ; Ok to exit
  477.  
  478. ;--------------------------------------------------------------------------;
  479. ; Leave                                                                    ;
  480. ;--------------------------------------------------------------------------;
  481.  
  482.         JMP     serint_exit         ; Go to common exit routine
  483.